#region Imported Namespaces
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Drawing;
using System.Text;
using System.Web;
using System.Web.Mail;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

using Utility = PHSRAG.Utility;
using Agreements = PHSRAG.Insight21.Agreements;
using UserContext = PHSRAG.Insight21.Context.UserContext;
using Policy = PHSRAG.Insight21.Policy;
using Email = PHSRAG.Insight21.InsightUtilities.Email;
using PHSRAG.Insight21.InsightUtilities;
using Header = PHSRAG.Insight21.InsightWebControls.Header;
using Annunciator = PHSRAG.WebControls.Annunciator;
using Pager = PHSRAG.WebControls.Pager;
using AgreementsSubNavigation = PHSRAG.Insight21.InsightWebControls.AgreementsSubNavigation;
using AgreementDetailsSubNavigation = PHSRAG.Insight21.InsightWebControls.AgreementDetailsSubNavigation;
using AgreementsConstants = PHSRAG.Insight21.InsightUtilities.Constants.AgreementsConstants;
using InsightDownloadBar = PHSRAG.Insight21.InsightWebControls.InsightDownloadBar;
using BreadCrumb = PHSRAG.WebControls.BreadCrumb;
using ActivityIndicator = PHSRAG.WebControls.ActivityIndicator;
using PostbackGuard = PHSRAG.WebControls.PostbackGuard;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Insight21.Common.DownloadBarHelper;
using PHSRAG.Insight21.Common;
using PHSRAG.Insight21.Common.Pages;

#endregion

namespace PHSRAG.Insight21.Agreements
{
	/// <summary>
	/// Code behind for AgreementsRevenueBreakdown.aspx page
	/// Contains business logic for populating data grid with revenue transaction information and related operations.
	/// </summary>
    public partial class AgreementsRevenueBreakdown : NoCachePage
	{
		#region Constants
		public const string RevenueBreakdownIdsKey = "RevenueBreakdownIDs_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string SortDirectionKey = "SortAscending_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string SortColumnKey = "SortColumn_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string CurrentPageIndexKey = "CurrentPageIndex_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryKey = "DictionaryKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryFundNumberKey = "DictionaryFundNumberKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryJournalStartDateKey = "DictionaryJournalStartDateKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryJournalEndDateKey = "DictionaryJournalEndDateKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryRevenueTotalKey = "DictionaryRevenueTotalKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string DictionaryPageReferrerKey = "DictionaryPageReferrerKey_8021F7C5-E6F6-4fac-AB4C-4291DFDA1E3B";
		public const string ExcelReportControlFilePath = "../../Agreements/Reports/RevenueBreakdownExcel.ascx";
		private const string IsDetailsFlagKey = "isDetails";
		#endregion

		#region Instance Variables (Private)
		private Policy.ICachePolicy cachePolicy;
		private Policy.ICachePolicy pageCachePolicy;
        private Policy.ViewStateCachePolicy viewStateCachePolicy;
        private ArrayList revenueBreakdownList = null;

		#endregion

		#region Private Properties
        /// <summary>
        /// Get and Set the flag which specifies the context of the page (Overview/Details)
        /// </summary>
        private bool IsDetail
        {
            get
            {
                object flag = viewStateCachePolicy.GetCachedObject(IsDetailsFlagKey);
                return (flag == null) ? false : (bool)flag;
            }
            set
            {
                viewStateCachePolicy.Cache(IsDetailsFlagKey, value);
            }
        }
        
        /// <summary>
		/// Private boolean property used to get/set if the sort order is ascending or descending.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private bool SortAscending
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return true;
				object sortAscending = revenueBreakdownPageCache[SortDirectionKey];
				return (sortAscending == null) ? true : (bool)sortAscending;
			}

			set
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) revenueBreakdownPageCache = new Hashtable();
				revenueBreakdownPageCache[SortDirectionKey] = value;
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);
			}
		}

		/// <summary>
		/// Private boolean property used to get/set the base sorting column.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private string SortColumn
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "FundNumber";
				object sortColumn = revenueBreakdownPageCache[SortColumnKey];
				return (sortColumn == null) ? "FundNumber" : (string)sortColumn;
			}

			set
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) revenueBreakdownPageCache = new Hashtable();
				revenueBreakdownPageCache[SortColumnKey] = value;
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);
			}
		}

		/// <summary>
		/// Private int property used to get/set the current page index.  
		/// PLEASE NOTE: that this property sets the dataGrid.CurrentPageIndex property.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.  
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private int CurrentPageIndex
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return 0;
				object currentPageIndex = revenueBreakdownPageCache[CurrentPageIndexKey];
				return (currentPageIndex == null) ? 0 : (int)currentPageIndex;
			}

			set
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) revenueBreakdownPageCache = new Hashtable();
				revenueBreakdownPageCache[CurrentPageIndexKey] = value;
				dataGrid.CurrentPageIndex = value;
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);
			}
		}

		/// <summary>
		/// Private string property used to get the requested fund number, if any.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private string DictionaryFundNumber
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
                
				if (revenueBreakdownPageCache == null) return "";
				object dictionaryFundNumber = revenueBreakdownPageCache[DictionaryFundNumberKey];
				return (dictionaryFundNumber == null) ? "" : (string)dictionaryFundNumber;
			}
		}

		/// <summary>
		/// Total from the source page, to display in the grid header
		/// </summary>
		private string DictionarySourceRevenueTotal
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "";
				object dictionarySourceRevenueTotal = revenueBreakdownPageCache[Keys.RevenueTotalKey];
				return (dictionarySourceRevenueTotal == null) ? "" : (string)dictionarySourceRevenueTotal;
			}
			set
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null)
					revenueBreakdownPageCache = new Hashtable();
				revenueBreakdownPageCache[Keys.RevenueTotalKey] = value;
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);
			}
		}


		/// <summary>
		/// Cumulative Flag originated on the Budget Detail page. 02-08-2008 jml29
		/// </summary>
		private int DictionaryCumulative
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return 0;
				object dictionaryCumulative = revenueBreakdownPageCache[Keys.CumulativeKey];
				return (dictionaryCumulative == null) ? 0 : (int)dictionaryCumulative;
			}
			set
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null)
					revenueBreakdownPageCache = new Hashtable();
				revenueBreakdownPageCache[Keys.CumulativeKey] = value;
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);
			}
		}

		/// <summary>
		/// Private string property used to get the requested start date.
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </summary>
		private string DictionaryJournalStartDate
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "";
				object dictionaryJournalStartDate = revenueBreakdownPageCache[DictionaryJournalStartDateKey];
				return (dictionaryJournalStartDate == null) ? "" : (string)dictionaryJournalStartDate;
			}
		}

		/// <summary>
		/// Private string property used to get the requested end date.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private string DictionaryJournalEndDate
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "";
				object dictionaryJournalEndDate = revenueBreakdownPageCache[DictionaryJournalEndDateKey];
				return (dictionaryJournalEndDate == null) ? "" : (string)dictionaryJournalEndDate;
			}
		}

		/// <summary>
		/// Private string property used to get the supplied revenue total, if any.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private string DictionaryRevenueTotal
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "";
				object dictionaryRevenueTotal = revenueBreakdownPageCache[DictionaryRevenueTotalKey];
				return (dictionaryRevenueTotal == null) ? "" : (string)dictionaryRevenueTotal;
			}
		}

		/// <summary>
		/// Private string property used to get the name of the referring page.
		/// </summary>
		/// <remarks>
		/// This and all properties required to re-establish the page are stored as name / value pairs in
		/// a hash table stored in the page cache under the key Keys.RevenueBreakdownPageKey.
		/// This enables the page to re-establish its state with minimal IO to what it was when
		/// the user last visited it.
		/// </remarks>
		private string DictionaryPageReferrer
		{
			get
			{
				Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
				if (revenueBreakdownPageCache == null) return "";
				object dictionaryPageReferrer = revenueBreakdownPageCache[DictionaryPageReferrerKey];
				return (dictionaryPageReferrer == null) ? "" : (string)dictionaryPageReferrer;
			}
		}
		#endregion

		#region Event Handlers (public)
		/// <summary>
		/// Invoked by the download bar when it catches an exception.
		/// </summary>
		/// <param name="sender">Control which raised the event</param>
		/// <param name="e">Argument associated with the event</param>
		protected void OnDownloadFailed(object sender, CommandEventArgs e)
		{
			annunciator.Title = "Following error(s) occurred while downloading";
			annunciator.Message = Utility.ExceptionReport.GetExceptionInfo((Exception)e.CommandArgument, false);
		}

		/// <summary>
		/// Handles Send By Email button clicks by preparing a MailMessage to send back to the InsightDownloadBar control
		/// </summary>
		/// <remarks>
		/// This method generates the raw information needed for the InsightDownloadBar to process and send an e-mail
		/// containing not only current totals information but a link back to the page with the correct session settings.
		/// To accomplish this, this page has to store all relevant session information into the database and then
		/// let the InsightDownloadBar know which query string-style row in the predefined table is the correct one.
		/// The page also needs to let the InsightDownloadBar know what the page's URL key is, and any additional summary
		/// information. For the purposes of this page, the summary information required is the current fund number (if any)
		/// and the revenue total.
		/// </remarks>
		public void OnSendByEmail(out string webConfigURLKey, out int queryId, out Hashtable summaryInfo)
		{
			try
			{
				webConfigURLKey = "Other.Agreements.RevenueBreakdownURL";

				string query = String.Format("{0}={1}&{2}={3}&{4}={5}",
					Keys.FundNumberKey, DictionaryFundNumber,
					Keys.RevenueStartDateKey, DictionaryJournalStartDate,
					Keys.RevenueEndDateKey, DictionaryJournalEndDate,
					Keys.PageReferrerKey, DictionaryPageReferrer);

				queryId = Convert.ToInt32(Utility.DataAccess.ExecuteScalar(Utility.DataAccess.GetConnectionString(), "InsertPageQuery",
					Utility.DataAccess.BuildSqlParameterArray("@query", SqlDbType.VarChar, query)));

				summaryInfo = new Hashtable();
				// If there is no single FundNumber associated wih the current state of this page and DictionaryFundNumber
				// therefore returns null, it will have the desired behavior.
				summaryInfo[Email.FundNumberKey] = DictionaryFundNumber;
				// revenueTotal.Text is used here instead of DictionaryRevenueTotal due to potential inefficient caching
				// issues involved with setting DictionaryRevenueTotal if no total was initially provided.
				// revenueTotal.Text will be set regardless of this issue, so it will work correctly here.
				summaryInfo[Email.DepositedIncomeKey] = revenueTotal.Text;
			}
			catch (Exception e)
			{
				webConfigURLKey = null;
				queryId = -1;
				summaryInfo = null;
				Utility.ExceptionReport.WriteToEventLog("Send By Email click handler", e, true, Utility.ExceptionReport.ReportType.Error);
			}
		}
		#endregion

		#region Event Handlers (private)
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                annunciator.Title = string.Empty;
                annunciator.Message = string.Empty;

                Policy.ResultsCache.PurgeObject(cachePolicy);
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                annunciator.Title = "Following error(s) occurred while executing the search";
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }
        /// <summary>
        /// Handler for the event raised when the "Clear Selection" button is clicked on thhe budget overview page
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            Policy.ResultsCache.PurgeObject(cachePolicy);
            dataGrid.Visible = false;
            pagerAboveDataGrid.Visible = pagerBelowDataGrid.Visible = false;
        }
        
        protected void OnFirstPage(object sender, CommandEventArgs e)
		{
			CurrentPageIndex = 0;
			LoadDataGrid();
		}

		/// <summary>
		/// OnItemCreated event of the DataGrid is used to indicate the sort column and the sort order.
		/// It references the private properties for SortColumn and SortAscending and sets the appropriate
		/// symbol in the appropriate column of the grid header.
		/// </summary>
		protected void OnItemCreated(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
		{
			if (e.Item.ItemType == ListItemType.Header)
			{
				Label sortSymbol = new Label();
				sortSymbol.Text = SortAscending ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
				sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

				TableCell cell = null;
				switch (SortColumn)
				{
					case "FundNumber": cell = e.Item.Cells[1]; break;
					// case "EntryDescription": cell = e.Item.Cells[2]; break;
					case "AccountNumber": cell = e.Item.Cells[3]; break;
					case "AccountName": cell = e.Item.Cells[4]; break;
					case "Amount": cell = e.Item.Cells[5]; break;
					case "DatePosted": cell = e.Item.Cells[6]; break;
					default: break;
				}

				if (cell != null)
					cell.Controls.Add(sortSymbol);
			}
		}

		/// <summary>
		/// Formats the revenue amount column as it is bound to the datagrid to display as a currency value.
		/// </summary>
		protected void OnItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs e)
		{
			try
			{
				if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
				{
					decimal revenueText = Math.Round(Convert.ToDecimal(e.Item.Cells[5].Text), 1);
					if (revenueText < 0)
						e.Item.Cells[5].CssClass = "DataGridNegativeCurrencyItem";
					e.Item.Cells[5].Text = revenueText.ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
				}
			}
			catch (Exception ex)
			{
				annunciator.Message = String.Format("{0} while attempting to format columns.", Utility.ExceptionReport.GetExceptionInfo(ex, false));
			}
		}

		protected void OnLastPage(object sender, CommandEventArgs e)
		{
			CurrentPageIndex = pagerAboveDataGrid.PageCount - 1;
			LoadDataGrid();
		}

		/// <summary>
		/// Purges the cache and sets the correct search context level before the breadcrumb performs a redirect.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void OnNavigate(object sender, CommandEventArgs e)
		{
			if (((CommandEventArgs)(e.CommandArgument)).CommandName == Convert.ToString((int)SearchCriteria.Level.Summary))
			{
				//set the search context's level to the correct level
				CommonSearchContext searchContext = (CommonSearchContext)cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
				searchContext.CurrentLevel = SearchCriteria.Level.Summary;
			}
			PurgeCache();
		}

		protected void OnNextPage(object sender, CommandEventArgs e)
		{
			++CurrentPageIndex;
			LoadDataGrid();
		}

		protected void Page_Load(object sender, System.EventArgs e)
		{
			insightDownloadBar.SQLReportName = "RevenueBreakdownReport";
			annunciator.Message = string.Empty;
			annunciator.Title = string.Empty;

			if (IsPostBack)
			{
				ManagePagination();
			}
			else if (postBackGuard.IsValid)
			{
				breadcrumb.Add("Revenue Breakdown", "AgreementsRevenueBreakdown.aspx", Utility.Settings.GetKeyValue("BreadCrumb.SubDetailPageLevel", 3));
                Hashtable incomingHashTable = (Hashtable)cachePolicy.GetCachedObject(AgreementsConstants.AgreementDetailsKey);

                bool isDetailsFlag = IsDetail = ((incomingHashTable == null) || (incomingHashTable[Keys.FundNumberKey] == null))
                    ? false : true;

                if (IsDetail)
                {
                    int budgetYear = (incomingHashTable[Keys.BudgetYearKey] == null) ? 0 : (int)incomingHashTable[Keys.BudgetYearKey];
                    string fundNumber = (string)incomingHashTable[Keys.FundNumberKey];
                    projectHeaderBar.LoadProjectHeader(fundNumber, -1, budgetYear);

                    CommonSearchContext searchContext = (CommonSearchContext)cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                    string startDate = (incomingHashTable[Keys.RevenueStartDateKey] != null) ?
                        incomingHashTable[Keys.RevenueStartDateKey].ToString() : string.Empty;

                    SearchCriteria commonSearchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());
                    if (commonSearchCriteria[InsightUtilities.Constants.RevenueFromDateKey] == null)
                        searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Detail,
                            Page.Request.Url.ToString(),
                            InsightUtilities.Constants.RevenueFromDateKey,
                            startDate == "1/1/1900" ? null : startDate,
                            "Revenue From Date", InsightWebControls.CommonSearch.LabelValueSeparator,
                            startDate == "1/1/1900" ? null : startDate);

                    if (commonSearchCriteria[InsightUtilities.Constants.RevenueToDateKey] == null)
                        searchContext.SetPrimarySearchCriteria(SearchCriteria.Level.Detail,
                            Page.Request.Url.ToString(),
                            InsightUtilities.Constants.RevenueToDateKey,
                            incomingHashTable[Keys.RevenueEndDateKey].ToString(),
                            "Revenue To Date", InsightWebControls.CommonSearch.LabelValueSeparator,
                            incomingHashTable[Keys.RevenueEndDateKey].ToString());
                }
                else
                    projectHeaderBar.Visible = false;
               
                dataGrid.PageSize = Utility.Settings.GetKeyValue("DataGrid.ItemsPerPage", 20);
				LoadDataGrid();
			}

			string dictionaryPageReferrer = DictionaryPageReferrer;
			string dictionaryFundNumber = DictionaryFundNumber;

			if (dictionaryPageReferrer == "BudgetOverview" ||
			  dictionaryPageReferrer == "ExpenseOverview" &&
			  dictionaryFundNumber == "")
			{
				agreementsSubNavigation.EnableOverviewNavigation = true;
				agreementDetailsSubNavigation.Visible = false;
			}
			else if (dictionaryPageReferrer == "BudgetDetails" ||
				  dictionaryPageReferrer == "ExpenseDetails" ||
				  dictionaryFundNumber != "")
			{
				agreementsSubNavigation.EnableOverviewNavigation = false;
				agreementDetailsSubNavigation.Visible = true;

                agreementDetailsSubNavigation.SelectedLink = AgreementDetailsSubNavigation.RevenueBreakdownCommand;
			}
			else
			{
				agreementsSubNavigation.EnableOverviewNavigation = true;
				agreementDetailsSubNavigation.Visible = false;
			}
		}

		protected void OnPreviousPage(object sender, CommandEventArgs e)
		{
			--CurrentPageIndex;
			LoadDataGrid();
		}

		protected void OnSort(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
		{
			if (e.SortExpression != string.Empty)
			{
				ProcessSortCriteria(e.SortExpression);
				CurrentPageIndex = 0;
				LoadDataGrid();
			}
		}

		/// <summary>
		/// Resets the subnavigation selected link and purges the cache before the 
		/// header performs a redirect.
		/// </summary>
		/// <param name="sender">Control which rasied the event.</param>
		/// <param name="e">Arguments associated with the event.</param>
		protected void OnHeaderNavigate(object sender, CommandEventArgs e)
		{
			PurgeCache();
			agreementsSubNavigation.Reset();
		}

		/// <summary>
		/// Purges the cache before the agreements subnavigation header performs a redirect.
		/// </summary>
		/// <param name="sender">Control which rasied the event.</param>
		/// <param name="e">Arguments associated with the event.</param>
		protected void OnSubNavigate(object sender, CommandEventArgs e)
		{
			PurgeCache();
		}

		/// <summary>
		/// Purges the cache before the agreement details subnavigation header performs a redirect.
		/// </summary>
		/// <param name="sender">Control which rasied the event.</param>
		/// <param name="e">Arguments associated with the event.</param>
		protected void OnDetailsSubNavigate(object sender, CommandEventArgs e)
		{
			PurgeCache();
		}
		#endregion

		#region Private Methods
		/// <summary>
		/// Get list of IDs for all applicable revenue transactions based on user context and defined parameters.
		/// </summary>
		/// <remarks>
		/// This method pulls in session data that the referring page should have populated. If the required information
		/// is not available, no revenue IDs will be returned. Before hitting the database for information, it first
		/// checks against the dictionary cache to see if the request has changed or if it is the first request. In either of
		/// these cases, the IDs will be loaded from the database; otherwise the page will simply be filled with existing
		/// information from the cache. The page is recached if the IDs have to be reloaded from the database.
		/// </remarks>
		private DataSet GetRevenueBreakdownIDs()
		{
			Hashtable revenueBreakdownPageCache = pageCachePolicy.GetCachedObject(Keys.RevenueBreakdownPageKey) as Hashtable;
			if (revenueBreakdownPageCache == null)
			{
				revenueBreakdownPageCache = new Hashtable();
			}

			Agreements.RevenueBreakdowns revenueBreakdownIDsCache =
			Policy.ResultsCache.GetObject(cachePolicy, RevenueBreakdownIdsKey) as Agreements.RevenueBreakdowns;

			Hashtable dictionary;

			if (!IsPostBack)
			{
				dictionary = pageCachePolicy.GetCachedObject(AgreementsConstants.AgreementDetailsKey) as Hashtable;
				if (dictionary == null)
				{
					// coming from BudgetOverview, not BudgetDetail
					dictionary = pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
				}

				if (dictionary == null)
				{
					dictionary = new Hashtable();
				}

				ViewState[DictionaryKey] = dictionary;
			}
			else
			{
				dictionary = ViewState[DictionaryKey] as Hashtable;
				if (dictionary == null)
				{
					throw new Exception("No Revenue Breakdown loading information available.");
				}
			}

			string passedFundNumber = string.Empty;
			string selectedBudgetDetailFundNumber = dictionary[Keys.SelectedBudgetDetailFundNumberKey] as String;
            

			DictionaryCumulative = Convert.ToInt32(dictionary[Keys.CumulativeKey]);
			if (selectedBudgetDetailFundNumber != null && selectedBudgetDetailFundNumber != string.Empty)
			{
				//we came in from the budget details page and a fund was selected so use that one
				//remove from the dictionary, and recache the dictionary.
				passedFundNumber = selectedBudgetDetailFundNumber;
				dictionary.Remove(Keys.SelectedBudgetDetailFundNumberKey);
				pageCachePolicy.Cache(Keys.IncomingDataKey, dictionary);
				ViewState[DictionaryKey] = dictionary;
			}
			else
			{
				passedFundNumber = (string)dictionary[Keys.FundNumberKey];
			}

			// Keys.JournalStart/EndDateKey have been changed to Keys.RevenueStart/EndDateKey
			// to prevent clobbering the dates expense details needs to load.
			// future pages which need to link to revenue breakdown must use these new keys.
			if (passedFundNumber == null) passedFundNumber = "";
			string passedJournalStartDate = dictionary[Keys.RevenueStartDateKey] as string;
			if (passedJournalStartDate == null) passedJournalStartDate = "";
			string passedJournalEndDate = dictionary[Keys.RevenueEndDateKey] as string;
			if (passedJournalEndDate == null) passedJournalEndDate = "";
			//			string passedRevenueTotal = dictionary[Keys.RevenueTotalKey] as string;
			//			if (passedRevenueTotal == null) passedRevenueTotal = "";
			string passedRevenueTotal = "";
			string passedPageReferrer = dictionary[Keys.PageReferrerKey] as string;
			if (passedPageReferrer == null) passedPageReferrer = "";

			if (!IsPostBack)
			{
				// Remove dictionary so it doesn't interfere with pages loading
				pageCachePolicy.UnCache(Keys.IncomingDataKey);
			}

			// Make sure the dictionary cache is either not initialized or the requested information has changed
			// before pulling new data from the backend
			if (revenueBreakdownIDsCache == null ||
				DictionaryFundNumber != passedFundNumber ||
				DictionaryJournalStartDate != passedJournalStartDate ||
				DictionaryJournalEndDate != passedJournalEndDate ||
				((passedRevenueTotal == null && DictionaryRevenueTotal != "") || (DictionaryRevenueTotal != passedRevenueTotal)) ||
				DictionaryPageReferrer != passedPageReferrer)
			{
				// Reset page index and flush cache
				CurrentPageIndex = 0;

				// Pull information from the passed dictionary and store in page cache
				revenueBreakdownPageCache[DictionaryFundNumberKey] = passedFundNumber;
				revenueBreakdownPageCache[DictionaryJournalStartDateKey] = passedJournalStartDate;
				revenueBreakdownPageCache[DictionaryJournalEndDateKey] = passedJournalEndDate;
				revenueBreakdownPageCache[DictionaryRevenueTotalKey] = passedRevenueTotal;
				revenueBreakdownPageCache[DictionaryPageReferrerKey] = passedPageReferrer;
				revenueBreakdownPageCache[Keys.RevenueTotalKey] = dictionary.ContainsKey(Keys.RevenueTotalKey) ?
						dictionary[Keys.RevenueTotalKey].ToString() : string.Empty;
				revenueBreakdownPageCache[Keys.CumulativeKey] = DictionaryCumulative;

				// Store current values for use in GetRevenueBreakdownResultSet
				pageCachePolicy.Cache(Keys.RevenueBreakdownPageKey, revenueBreakdownPageCache);

				// Pull requested list of revenue breakdown IDs from the database
				revenueBreakdownIDsCache = GetRevenueBreakdownResultSet(ResultSetType.IDsOnly);
				Policy.ResultsCache.SetObject(cachePolicy, RevenueBreakdownIdsKey, revenueBreakdownIDsCache);

                InsightWebControls.OverviewSearch overviewSearch = (InsightWebControls.OverviewSearch)commonSearch1.EmbeddedSearchControl;
			}

			return revenueBreakdownIDsCache.GetDataContainer();
		}

		/// <summary>
		/// Get details for all revenue transactions within the current index range
		/// </summary>
		/// <remarks>
		/// This method lazy loads an ArrayList with only the required data needed for the current page
		/// displayed by the DataGrid, which can then be bound by said DataGrid. The index range loaded is from
		/// (CurrentPageIndex * PageSize) to Min(startIndex + PageSize, total IDs). The FirstRecord and LastRecord
		/// properties of the pagers are also set to these values.
		/// </remarks>
		/// <param name="revenueBreakdownIDs">DataSet populated with RevenueBreakdown IDs to be displayed</param>
		private ArrayList GetRevenueBreakdownList(DataSet revenueBreakdownIDs)
		{
			int startIndex = CurrentPageIndex * dataGrid.PageSize;
			int endIndex = Math.Min(startIndex + dataGrid.PageSize, revenueBreakdownIDs.Tables[0].Rows.Count);
			pagerBelowDataGrid.FirstRecord = pagerAboveDataGrid.FirstRecord = startIndex + 1;
			pagerBelowDataGrid.LastRecord = pagerAboveDataGrid.LastRecord = endIndex;

			if (revenueBreakdownList == null)
			{
				revenueBreakdownList = new ArrayList();

				for (int i = startIndex; i < endIndex; ++i)
				{
					int revenueBreakdownID = (int)(revenueBreakdownIDs.Tables[0].Rows[i]["TransactionID"]);
					Agreements.RevenueBreakdown revenueBreakdown = new Agreements.RevenueBreakdown(cachePolicy);
					revenueBreakdown.Load(Utility.DataAccess.GetConnectionString(), Session.SessionID,
						((UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey)).DomainUserId,
						revenueBreakdownID);
					revenueBreakdownList.Add(revenueBreakdown);
				}
			}

			return revenueBreakdownList;
		}

		/// <summary>
		/// GetRevenueBreakdownResultSet instanciates the RevenueBreakdowns object and returns
		/// a resultset.  There are 2 resultset types:
		///		1)	IDsOnly - Returns a table of IDs based on user-defined filter criteria, plus a total if one is not provided.
		///		2)  Full    - Returns a full resultset of the revenue transaction data.
		/// </summary>
		private Agreements.RevenueBreakdowns GetRevenueBreakdownResultSet(ResultSetType resultType)
		{
			Agreements.RevenueBreakdowns revenueBreakdowns = new Agreements.RevenueBreakdowns();
			UserContext userContext = (UserContext)cachePolicy.GetCachedObject(UserContext.CacheKey);
			System.Diagnostics.Debug.Assert(userContext != null);
			bool searchByFundNumber = DictionaryFundNumber != string.Empty;
            Hashtable h = (Hashtable)cachePolicy.GetCachedObject(AgreementsConstants.AgreementDetailsKey);
            SearchCriteria crit = ((CommonSearchContext)cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString());
            // If no total data is available in the cached dictionary entries, then populate it through load along with the IDs.
            //Tkt:-9219
            Hashtable accountno = (Hashtable)cachePolicy.GetCachedObject(AgreementsConstants.AgreementDetailsKey);
            Hashtable dictionary = pageCachePolicy.GetCachedObject(Keys.AccountNumberKey) as Hashtable;
            if (accountno == null)
            {
              
                if (dictionary == null)
                    throw new Exception("Fund Number for which Transaction to be displayed is not provided");
                    
                    string Accountnumber = dictionary[Keys.AccountNumberKey] as string;
                    revenueBreakdowns.Load(Utility.DataAccess.GetConnectionString(), Session.SessionID,
                        (searchByFundNumber)
                            ? (object)userContext.DomainUserId
                        : (object)crit,
                        (searchByFundNumber) ? DictionaryFundNumber : string.Empty,
                        crit[InsightUtilities.Constants.RevenueFromDateKey],
                        crit[InsightUtilities.Constants.RevenueToDateKey],
                        ((DictionaryRevenueTotal == "") ? false : true),
                        SortColumn,
                        (SortAscending) ? "asc" : "desc",
                        resultType,
                        DictionaryCumulative,
                        Accountnumber != "&nbsp;" ? Accountnumber : crit[InsightUtilities.Constants.RevenueAccountNumber]);
                
            }
            else
            {
                string Accountnumber = accountno[Keys.AccountNumberKey] as string;
                revenueBreakdowns.Load(Utility.DataAccess.GetConnectionString(), Session.SessionID,
                    (searchByFundNumber)
                        ? (object)userContext.DomainUserId
                    : (object)crit,
                    (searchByFundNumber) ? DictionaryFundNumber : string.Empty,
                    crit[InsightUtilities.Constants.RevenueFromDateKey],
                    crit[InsightUtilities.Constants.RevenueToDateKey],
                    ((DictionaryRevenueTotal == "") ? false : true),
                    SortColumn,
                    (SortAscending) ? "asc" : "desc",
                    resultType,
                    DictionaryCumulative,
                    Accountnumber != "&nbsp;" ? Accountnumber : crit[InsightUtilities.Constants.RevenueAccountNumber]);
            }

            //Tkt:-9219 End
			return revenueBreakdowns;
		}

		/// <summary>
		/// Populate the page's DataGrid with revenue transaction data
		/// </summary>
		/// <remarks>
		/// To fill out the DataGrid, this method will first create a list of revenue breakdown IDs that match
		/// the requested filtration criteria. These IDs are cached in page cache data and lazy loaded as needed to
		/// display only the current page. When the current page's set of IDs have been loaded, they are bound to
		/// the DataGrid and displayed to the user.
		/// This method will also set a revenue total label, an "as of" date label, and the current page and total
		/// page counts of the pagers.
		/// </remarks>
		private void LoadDataGrid()
		{
			try
			{
				DataSet revenueBreakdownIDs = GetRevenueBreakdownIDs();
				if (revenueBreakdownIDs.Tables[0].Rows.Count == 0)
					throw new Exception("No Revenue Breakdown information available for user / fund(s).");
				dataGrid.VirtualItemCount = pagerBelowDataGrid.RecordCount = pagerAboveDataGrid.RecordCount =
					revenueBreakdownIDs.Tables[0].Rows.Count;

				// Check if total data has been given to this page already through page cache data. If not, get it from
				// the cached RevenueBreakdownIDs object, which should have populated it on load.
				if (DictionaryRevenueTotal == "")
					revenueTotal.Text = ((decimal)(revenueBreakdownIDs.Tables[1].Rows[0]["RevenueTotal"])).ToString("c", PHSRAG.WebControls.Helper.ZeroDecimals());
				else
					revenueTotal.Text = DictionaryRevenueTotal;

				// Set the "as of" date label to the format "As of <month>/<day>/<year>" if the referring page is not
				// Expense Overview. If the referring page is Expense Overview or Expense Details, 
				// show "For <full month>, <year>" instead
				if (DictionaryPageReferrer == "ExpenseOverview" || DictionaryPageReferrer == "ExpenseDetails")
					feedDate.Text = string.Format("For {0}", (DateTime.Parse(DictionaryJournalEndDate)).ToString("y"));
				else
					feedDate.Text = string.Format("As of {0}", (DateTime.Parse(DictionaryJournalEndDate)).ToString("d"));

				currentYearRevenue.Text = String.Format("(Current Fiscal Year Revenue: {0})", DictionarySourceRevenueTotal);

				int pageCount = (pagerAboveDataGrid.RecordCount / dataGrid.PageSize) +
					(int)(((pagerAboveDataGrid.RecordCount % dataGrid.PageSize) == 0) ? 0 : 1);
				pagerBelowDataGrid.PageCount = pagerAboveDataGrid.PageCount = pageCount;
				pagerBelowDataGrid.CurrentPage = pagerAboveDataGrid.CurrentPage = CurrentPageIndex + 1;

				ArrayList revenueBreakdownList = GetRevenueBreakdownList(revenueBreakdownIDs);
				if ((revenueBreakdownList != null) && (revenueBreakdownList.Count > 0))
				{
					dataGrid.DataSource = revenueBreakdownList;
					dataGrid.DataBind();
				}

				dataGrid.Visible = pagerAboveDataGrid.Visible = pagerBelowDataGrid.Visible = (dataGrid.Items.Count > 0);
				if (dataGrid.Visible)
					ManagePagination();
				else
					annunciator.Message = "No revenue breakdown found for the user";
			}
			catch (Exception e)
			{
				dataGrid.Visible = pagerAboveDataGrid.Visible = pagerBelowDataGrid.Visible = false;
				annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(e, false);
			}
		}

		private void ManagePagination()
		{
			int currentPageIndex = CurrentPageIndex;
			dataGrid.CurrentPageIndex = currentPageIndex;

			int startIndex = currentPageIndex * dataGrid.PageSize;

			pagerBelowDataGrid.FirstRecord = pagerAboveDataGrid.FirstRecord = startIndex + 1;
			pagerBelowDataGrid.LastRecord = pagerAboveDataGrid.LastRecord =
				Math.Min(startIndex + dataGrid.PageSize, dataGrid.VirtualItemCount);
		}

		/// <summary>
		/// ProcessSortCriteria takes the sort expression from the DataGrid and handles toggling the
		/// sort direction, setting the sort column, and clearing the cache in preparation for a sort.
		/// </summary>
		private void ProcessSortCriteria(string sortExpression)
		{
			// If a sort was clicked and the column was the same as the current sort column,
			// We must toggle the sort order and clear the cache if one exists already. 

			if (sortExpression != string.Empty)
			{
				if (SortColumn.Trim().ToLower() == sortExpression.Trim().ToLower())
				{
					// Toggle the sort order.
					SortAscending = !SortAscending;
				}
				else  // First time sort ascending.
				{
					SortAscending = true;
				}

				SortColumn = sortExpression;

				// Clean cache if new sort.
				Policy.ResultsCache.PurgeObject(cachePolicy);
			}
		}

		/// <summary>
		/// Uncaches all objects with data for this page.
		/// </summary>
		private void PurgeCache()
		{
			System.Diagnostics.Trace.WriteLine("Purging RevenueBreakdown...");
			pageCachePolicy.UnCache(Keys.RevenueBreakdownPageKey);
			Policy.ResultsCache.PurgeObject(cachePolicy);
		}
		#endregion

		#region Web Form Designer generated code
		/// <summary>
		/// Handler for the event raised when the page is being initialized.
		/// Retrieve the cache policy in force. Deposit event handlers to support the datagrid pagination.
		/// </summary>
		override protected void OnInit(EventArgs e)
		{
			InitializeComponent();
			base.OnInit(e);

			cachePolicy = (Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey];
			pageCachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];
            viewStateCachePolicy = new PHSRAG.Insight21.Policy.ViewStateCachePolicy(this.ViewState);
        }

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
		}
		#endregion
	}
}

// --- EOF ---